<template>
  <div class="code-editor-container">
    <!-- 头部工具栏 -->
    <div class="toolbar">
      <el-select v-model="currentLanguage" @change="handleLanguageChange" style="width: 120px">
        <el-option label="Vue" value="vue" />
      </el-select>
      <el-button type="success" @click="saveAndRun">
        <el-icon><DocumentAdd /></el-icon>
        保存
      </el-button>
      <el-button @click="clearCode">
        <el-icon><Delete /></el-icon>
        清空
      </el-button>
      <el-button @click="$router.back()">
        <el-icon><ArrowLeft /></el-icon>
        返回
      </el-button>
    </div>

    <!-- 编辑器和预览区域 -->
    <div class="editor-layout">
      <!-- 代码编辑器 -->
      <div class="editor-panel">
        <div class="panel-header">
          <span>代码编辑器</span>
          <span class="language-tag">{{ currentLanguage.toUpperCase() }}</span>
        </div>
        <div ref="editorRef" class="editor-content"></div>
      </div>

      <!-- 预览区域 -->
      <div class="preview-panel">
        <div class="panel-header">
          <span>预览</span>
          <div>
            <el-button size="small" @click="refreshPreview"> 刷新预览 </el-button>
            <el-button size="small" @click="openPreivew"> 打开预览页面 </el-button>
          </div>
        </div>
        <div class="preview-content">
          <!-- 保存信息表单 -->
          <div class="save-info-form">
            <el-form :model="saveForm" label-width="100px" size="small">
              <el-form-item label="模板名称">
                <el-input v-model="saveForm.templateName" placeholder="请输入模板名称" :disabled="isEdit" clearable />
              </el-form-item>

              <el-form-item label="文件名称">
                <el-input v-model="saveForm.bindFileName" placeholder="请输入文件名称（英文大写字母开头，只允许英文字母）" @input="handleFileNameChange" :disabled="isEdit" clearable>
                  <template #append>.vue</template>
                </el-input>
                <div class="form-tip">文件名只允许英文字母，必须以大写字母开头，如：Button、UserList等</div>
              </el-form-item>

              <el-form-item label="模板类型">
                <el-select v-model="saveForm.type" style="width: 100%" :disabled="isEdit" @change="handleTplTypeChange">
                  <el-option label="单页" value="page" />
                  <el-option label="列表页" value="list" />
                  <el-option label="详情页" value="detail" />
                </el-select>
              </el-form-item>
            </el-form>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick, onUnmounted } from "vue";
import { ElMessage } from "element-plus";
import { VideoPlay, Delete, MagicStick, Refresh, DocumentAdd } from "@element-plus/icons-vue";
import { EditorView, basicSetup } from "codemirror";
import { EditorState } from "@codemirror/state";
import { html } from "@codemirror/lang-html";
import { vue } from "@codemirror/lang-vue";
import { oneDarkTheme } from "@codemirror/theme-one-dark";
import { getTemplateById } from "@/api/webbase";
import { createTemplate, updateTemplate, updatePreview } from "@/api/webbase";
import { useRoute, useRouter } from "vue-router";
import { detailPage, listPage, singlePage } from "@/utils/vuetpls"; // 详情、列表、单页的初始模板，含有最基本的接口请求要素

// 响应式数据
const editorRef = ref<HTMLElement>();
const previewRef = ref<HTMLIFrameElement>();
const editorView = ref<EditorView>();
const currentLanguage = ref("vue");
const templateContent = ref("");
const route = useRoute();
const router = useRouter();
const isEdit = route.query.id !== undefined;
// 保存对话框相关数据
const saveForm = ref({
  templateName: "",
  bindFileName: "",
  bindComponentString: "",
  templateContentCache: "",
  type: "page"
});

// 消息监听器的引用，用于清理
let messageListener: ((event: MessageEvent) => void) | null = null;
let timeoutId: number | null = null;

// 默认代码模板, 默认是单页
const defaultTemplates = {
  vue: singlePage
};

/**
 * 获取语言扩展
 * @param language 编程语言
 * @returns CodeMirror 语言扩展
 */
const getLanguageExtension = (language: string) => {
  switch (language) {
    case "html":
      return html();
    case "vue":
      return vue();
    default:
      return vue();
  }
};

/**
 * 初始化编辑器
 */
const initEditor = () => {
  if (editorView.value) {
    editorView.value.destroy();
  }

  if (!editorRef.value) return;

  const startState = EditorState.create({
    doc: templateContent.value || defaultTemplates[currentLanguage.value as keyof typeof defaultTemplates],
    extensions: [
      basicSetup,
      oneDarkTheme,
      getLanguageExtension(currentLanguage.value),
      EditorView.updateListener.of((update) => {
        if (update.docChanged) {
          templateContent.value = update.state.doc.toString();
        }
      })
    ]
  });

  editorView.value = new EditorView({
    state: startState,
    parent: editorRef.value
  });
};

/**
 * 处理语言切换
 * @param language 新选择的语言
 */
const handleLanguageChange = (language: string) => {
  templateContent.value = defaultTemplates[language as keyof typeof defaultTemplates];
  nextTick(() => {
    initEditor();
  });
};

/**
 * 清空代码
 */
const clearCode = () => {
  if (editorView.value) {
    editorView.value.dispatch({
      changes: {
        from: 0,
        to: editorView.value.state.doc.length,
        insert: ""
      }
    });
    templateContent.value = "";
  }
  ElMessage.success("代码已清空");
};

/**
 * 刷新预览
 */
const refreshPreview = () => {
  updatePreview({
    content: templateContent.value
  }).then((res) => {
    console.log(res, "更新结果");
    if (res.status === 200) {
      ElMessage.success("预览更新成功");
    } else {
      ElMessage.error("预览更新失败");
    }
  });
};

const openPreivew = () => {
  window.open("/preview", "_blank");
};

/**
 * 保存并运行代码
 */
const saveAndRun = async () => {
  if (!saveForm.value.templateName.trim()) {
    ElMessage.error("请先填写模板名称");
    return;
  }
  if (!saveForm.value.bindFileName.trim()) {
    ElMessage.error("请先填写文件名称");
    return;
  }

  // 验证文件名格式（只允许英文字母，必须以大写字母开头）
  const fileNamePattern = /^[A-Z][a-zA-Z]*$/;
  if (!fileNamePattern.test(saveForm.value.bindFileName)) {
    ElMessage.error("文件名称只允许英文字母，且必须以大写字母开头");
    return;
  }

  saveForm.value.templateContentCache = templateContent.value;

  try {
    let res;
    if (isEdit) {
      // 编辑模式：调用updateTemplate接口
      const editId = route.query.id as string;
      res = await updateTemplate(editId, {
        templateName: saveForm.value.templateName,
        bindFileName: saveForm.value.bindFileName,
        bindComponentString: saveForm.value.bindComponentString,
        templateContentCache: saveForm.value.templateContentCache,
        type: saveForm.value.type
      });
    } else {
      // 新建模式：调用createTemplate接口
      res = await createTemplate(saveForm.value);
    }

    if (res.status === 200) {
      ElMessage.success(isEdit ? "更新成功" : "保存成功");
      router.back();
    } else {
      ElMessage.error(isEdit ? "更新失败" : "保存失败");
    }
  } catch (error) {
    console.error("保存失败:", error);
    ElMessage.error(isEdit ? "更新失败" : "保存失败");
  }
};

/**
 * 处理文件名变化，自动生成组件字符串
 * @param fileName 文件名（来源：用户输入）
 */
const handleFileNameChange = (fileName: string) => {
  if (fileName) {
    // 只允许英文字母，过滤掉其他字符
    const filteredName = fileName.replace(/[^a-zA-Z]/g, "");

    if (filteredName) {
      // 确保首字母大写
      const formattedName = filteredName.charAt(0).toUpperCase() + filteredName.slice(1);
      saveForm.value.bindFileName = formattedName;
      saveForm.value.bindComponentString = `<${formattedName} />`;
    } else {
      // 如果过滤后为空，清空相关字段
      saveForm.value.bindFileName = "";
      saveForm.value.bindComponentString = "";
    }
  } else {
    // 如果输入为空，清空相关字段
    saveForm.value.bindFileName = "";
    saveForm.value.bindComponentString = "";
  }
};

/**
 * 初始化预览区域
 */
const initPreview = () => {
  if (!previewRef.value) return;

  const doc = previewRef.value.contentDocument;
  if (doc) {
    doc.open();
    doc.write(
      '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>预览</title></head><body><div style="padding: 20px; text-align: center; color: #666;">请点击"运行代码"按钮查看效果</div></body></html>'
    );
    doc.close();
  }
};

/**
 * 加载编辑数据
 * @param id 模板ID
 */
const loadEditData = async (id: string) => {
  try {
    const response = await getTemplateById(id);
    if (response.data) {
      const data = response.data as any;
      console.log(response.data,'data');

      const { templateName, bindFileName, bindComponentString, templateContentCache, type } = data;

      // @ts-ignore 填充保存表单数据
      saveForm.value = {
        templateName: templateName || "",
        bindFileName: bindFileName || "",
        bindComponentString: bindComponentString || "",
        type: type || "normal"
      };

      // 设置编辑器内容
      if (templateContentCache) {
        templateContent.value = templateContentCache;
        // 如果编辑器已初始化，更新内容
        if (editorView.value) {
          editorView.value.dispatch({
            changes: {
              from: 0,
              to: editorView.value.state.doc.length,
              insert: templateContentCache
            }
          });
        }
      }

      ElMessage.success("编辑数据加载成功");
    } else {
      ElMessage.error("获取编辑数据失败");
    }
  } catch (error) {
    console.error("加载编辑数据失败:", error);
    ElMessage.error("加载编辑数据失败，请重试");
  }
};

const handleTplTypeChange = (value: string) => {
  console.log(value);
  if (value === "detail") {
    templateContent.value = detailPage;
  } else if (value === "list") {
    templateContent.value = listPage;
  } else if (value === "page") {
    templateContent.value = singlePage;
  }

  nextTick(() => {
    initEditor();
  });
};

// 组件挂载时初始化编辑器和预览
onMounted(() => {
  // 检查是否为编辑模式
  const editId = route.query.id as string;

  // 设置默认模板内容
  templateContent.value = defaultTemplates[currentLanguage.value as keyof typeof defaultTemplates];

  nextTick(async () => {
    initEditor();
    initPreview();

    // 如果存在ID，则加载编辑数据
    if (editId) {
      await loadEditData(editId);
    }
  });
});

// 组件卸载时清理资源
onUnmounted(() => {
  if (messageListener) {
    window.removeEventListener("message", messageListener);
    messageListener = null;
  }
  if (timeoutId) {
    clearTimeout(timeoutId);
    timeoutId = null;
  }
});
</script>

<style lang="less" scoped>
.code-editor-container {
  height: calc(100vh - 78px);
  display: flex;
  flex-direction: column;
  background: #f5f5f5;
}

.toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px;
  background: white;
  border-bottom: 1px solid #e0e0e0;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.editor-layout {
  flex: 1;
  display: flex;
  gap: 1px;
  background: #e0e0e0;
  height: 100%;
}
.editor-panel {
  width: 70%;
}
.preview-panel {
  width: 30%;
}
.editor-panel,
.preview-panel {
  display: flex;
  flex-direction: column;
  background: white;
}

.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #fafafa;
  border-bottom: 1px solid #e0e0e0;
  font-weight: 500;
  color: #333;
}

.language-tag {
  background: #007bff;
  color: white;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: normal;
}

.editor-content {
  flex: 1;
  overflow: hidden;

  :deep(.cm-editor) {
    height: 100%;
    font-size: 14px;
  }

  :deep(.cm-scroller) {
    font-family: "Fira Code", "Monaco", "Menlo", "Ubuntu Mono", monospace;
  }
}

.preview-content {
  flex: 1;
  padding: 0;
  background: white;
  position: relative;
  display: flex;
  flex-direction: column;
}

.save-info-form {
  padding: 16px;
  border-bottom: 1px solid #e0e0e0;
  background: #fafafa;
}

.iframe-container {
  flex: 1;
  position: relative;
  border: 1px solid #ddd;
  border-radius: 4px;
  overflow: hidden;
}

.form-tip {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
  line-height: 1.4;
}

.preview-iframe {
  width: 100%;
  height: 100%;
  border: none;
  background: white;
}

.loading-overlay,
.error-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  border-radius: 6px;
}

.loading-overlay {
  background-color: rgba(255, 255, 255, 0.9);
}

.error-overlay {
  background-color: rgba(254, 226, 226, 0.95);
}

.loading-text {
  color: #409eff;
  font-size: 16px;
  font-weight: 500;
}

.error-text {
  color: #f56c6c;
  font-size: 14px;
  text-align: center;
  padding: 20px;
  max-width: 80%;
  word-wrap: break-word;
}

/* 表单提示样式 */
.form-tip {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
  line-height: 1.4;
}

/* 对话框样式 */
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .editor-layout {
    flex-direction: column;
  }

  .editor-panel,
  .preview-panel {
    min-height: 300px;
  }

  .toolbar {
    flex-wrap: wrap;
    gap: 8px;
  }
}
</style>
